package mx.ipn.presentacion.empleado;

import java.util.Date;

import mx.ipn.persistencia.FabricaDeDAOs;
import mx.ipn.to.*;

import java.util.ArrayList;

public class ProcesoNomina {
	FabricaDeDAOs fabrica = FabricaDeDAOs.getFabricaDeDAOs(1);
	EmpleadoTO[] arrEmpleadoTO = null;
	HorarioTO[] arrHorarioTO = null;
	DatosNominaTO[] arrDatosTO = null;

	ArrayList<BitacoraAsistenciaTO> listBitacoraAsisTO = new ArrayList<BitacoraAsistenciaTO>();
	ArrayList<BitacoraHorarioTO> listBitacoraHorarioTO = new ArrayList<BitacoraHorarioTO>();
	ArrayList<HorarioTO> listHorarioTO = new ArrayList<HorarioTO>();
	ArrayList<DatosNominaTO> listDatosTO = new ArrayList<DatosNominaTO>();
	ArrayList<Double> listTotalHoras = new ArrayList<Double>();

	public ArrayList<Short> listaMeses(Date inicio, Date Fin) {
		ArrayList<Short> listaMes = new ArrayList<Short>();

		String mesIni = FechaHoraTO.getFecha(inicio).toString().substring(5, 7);
		String mesFin = FechaHoraTO.getFecha(Fin).toString().substring(5, 7);
		int mesI = Integer.parseInt(mesIni);
		int mesF = Integer.parseInt(mesFin);
		for (int x = mesI; x <= mesF; x++) {
			listaMes.add((short) x);
		}
		return listaMes;
	}

	public void horarioEnRango(Date inicio, Date fin) {
		listHorarioTO = fabrica.getHorarioDAO().selectHorarioByRangoInicio(
				FechaHoraTO.getFecha(inicio), FechaHoraTO.getFecha(fin));
		ArrayList<EmpleadoTO> listEmpleadoTO = new ArrayList<EmpleadoTO>();
		listEmpleadoTO = fabrica.getEmpleadoDAO().selectEmpleadoActivo();
		arrEmpleadoTO = (EmpleadoTO[]) listEmpleadoTO
				.toArray(new EmpleadoTO[listEmpleadoTO.size()]);
		arrDatosTO = new DatosNominaTO[arrEmpleadoTO.length];

		for (int x = 0; x < arrEmpleadoTO.length; x++) {
			DatosNominaTO auxTO = new DatosNominaTO();

			auxTO.setEmpleadoTO(arrEmpleadoTO[x]);
			auxTO.setFecha(new Date());
			auxTO.setInicioPeriodo(new Date(inicio.getTime()));
			auxTO.setFinPeriodo(new Date(fin.getTime()));

			arrDatosTO[x] = auxTO;
		}

		MotivoTO acceso = fabrica.getMotivoDAO().findMotivoByNombreTipoMotivo(
				"inicio de sesion", (short) 1);
		MotivoTO baja = fabrica.getMotivoDAO().findMotivoByNombreTipoMotivo(
				"fin de sesion", (short) 1);
		// proceso que coloca asistencias dependiendo de los accesos al sistema
		for (int x = 0; x < arrDatosTO.length; x++) {
			boolean bandera = true;
			boolean motivo = true;
			int idOperacion = 1;

			UsuarioTO usuarioTO = fabrica.getUsuarioDAO()
					.findUsuarioByEmpleado(
							arrDatosTO[x].getEmpleadoTO().getIdEmpleado());

			BitacoraAccesoTO bAccesoTO = null;
			BitacoraAccesoTO bBajaTO = null;

			while (bandera == true && usuarioTO != null) {
				if (motivo == true) {
					bAccesoTO = fabrica.getBitacoraAccesoDAO()
							.findBitacoraAccesoByIdUsuarioMotivo(idOperacion,
									FechaHoraTO.getFecha(inicio),
									usuarioTO.getIdUsuario(),
									acceso.getIdMotivo());
					motivo = false;
					bBajaTO = null;
					if (bAccesoTO != null)
						idOperacion = bAccesoTO.getIdOperacion();
					else
						bandera = false;

				} else {
					bBajaTO = fabrica.getBitacoraAccesoDAO()
							.findBitacoraAccesoByIdUsuarioMotivo(idOperacion,
									FechaHoraTO.getFecha(inicio),
									usuarioTO.getIdUsuario(),
									baja.getIdMotivo());
					motivo = true;
					if (bBajaTO != null)
						idOperacion = bBajaTO.getIdOperacion();
					else
						bandera = false;
				}

				if (bBajaTO != null && bAccesoTO != null) {
					for (int y = 0; y < listHorarioTO.size(); y++) {
						if (listHorarioTO.get(y).getFechaInicio().getTime() <= bAccesoTO
								.getFecha().getTime()
								&& listHorarioTO.get(y).getFechaTermino()
										.getTime() >= bAccesoTO.getFecha()
										.getTime()) {
							long tiempoInicio = bAccesoTO.getFecha().getTime()
									+ bAccesoTO.getHora().getTime();
							long tiempoFin = bBajaTO.getFecha().getTime()
									+ bBajaTO.getHora().getTime();
							long tiempoHorario = (listHorarioTO.get(y)
									.getTurnoTO().getDuracion().getTime() - FechaHoraTO
									.getHora("00:00:00").getTime());
							long operacion = (tiempoFin - tiempoInicio
									+ (long) 60000 - tiempoHorario);

							if (operacion > (long) 0) {
								BitacoraAsistenciaTO biAsisTO = fabrica
										.getBitacoraAsistenciaDAO()
										.findBitacoraAsistenciaByFechaEmpleadoConsiderada(
												FechaHoraTO.getFecha(bAccesoTO
														.getFecha()),
												arrDatosTO[x].getEmpleadoTO()
														.getIdEmpleado(), false);
								if (biAsisTO != null) {
									biAsisTO.setIdEmpleado(arrDatosTO[x]
											.getEmpleadoTO().getIdEmpleado());
									biAsisTO.setIdMotivo(4);
									biAsisTO.setDescripcion("");
									biAsisTO.setIdUsuario(biAsisTO
											.getListUsuarioTO()[0]
											.getIdUsuario());
									fabrica.getBitacoraAsistenciaDAO()
											.updateBitacoraAsistencia(biAsisTO);
								}
							}
						}
					}
				}

			}
		}
		// proceso que modifica faltas y asistencias dependiendo del dia festivo
		MotivoTO falta = fabrica.getMotivoDAO().findMotivoByNombreTipoMotivo(
				"falta", (short) 2);
		MotivoTO asistencia = fabrica.getMotivoDAO()
				.findMotivoByNombreTipoMotivo("asistencia", (short) 2);
		MotivoTO festivo = fabrica.getMotivoDAO().findMotivoByNombreTipoMotivo(
				"festivo laborado", (short) 2);
		MotivoTO vacaciones = fabrica.getMotivoDAO()
				.findMotivoByNombreTipoMotivo("vacaciones", (short) 2);

		ArrayList<Short> listaMes = listaMeses(inicio, fin);
		for (int x = 0; x < listaMes.size(); x++) {
			ArrayList<DiaFestivoTO> listaDiaTO = fabrica.getDiaFestivoDAO()
					.selectDiasFestivosByMes(listaMes.get(x));
			for (int y = 0; y < listaDiaTO.size(); y++) {
				for (int z = 0; z < arrDatosTO.length; z++) {
					String fechaIn = FechaHoraTO.getFecha(inicio).toString();
					BitacoraAsistenciaTO auxTO = fabrica
							.getBitacoraAsistenciaDAO()
							.findBitacoraAsistenciaByFechaEmpleadoConsiderada(
									FechaHoraTO.getFecha(fechaIn
											.substring(0, 4)
											+ "/"
											+ String.valueOf(listaDiaTO.get(y)
													.getMes())
											+ "/"
											+ String.valueOf(listaDiaTO.get(y)
													.getDia())),
									arrDatosTO[z].getEmpleadoTO()
											.getIdEmpleado(), false);

					if (auxTO != null) {
						auxTO.setIdEmpleado(arrDatosTO[z].getEmpleadoTO()
								.getIdEmpleado());
						auxTO.setDescripcion("");
						auxTO.setIdUsuario(auxTO.getListUsuarioTO()[0]
								.getIdUsuario());
						if (auxTO.getListMotivoTO()[0].getIdMotivo() == asistencia
								.getIdMotivo()) {
							auxTO.setIdMotivo(festivo.getIdMotivo());
						} else if (auxTO.getListMotivoTO()[0].getIdMotivo() == falta
								.getIdMotivo()) {
							auxTO.setIdMotivo(asistencia.getIdMotivo());
						}

						fabrica.getBitacoraAsistenciaDAO()
								.updateBitacoraAsistencia(auxTO);
					}
				}
			}
		}

		// calculo de horas trabajadas considerando los dias festivos
		for (int x = 0; x < arrDatosTO.length; x++) {
			boolean bandera = true;
			boolean motivo = true;
			int idOperacion = 1;

			UsuarioTO usuarioTO = fabrica.getUsuarioDAO()
					.findUsuarioByEmpleado(
							arrDatosTO[x].getEmpleadoTO().getIdEmpleado());

			BitacoraAccesoTO bAccesoTO = null;
			BitacoraAccesoTO bBajaTO = null;

			while (bandera == true && usuarioTO != null) {
				if (motivo == true) {
					bAccesoTO = fabrica.getBitacoraAccesoDAO()
							.findBitacoraAccesoByIdUsuarioMotivo(idOperacion,
									FechaHoraTO.getFecha(inicio),
									usuarioTO.getIdUsuario(),
									acceso.getIdMotivo());
					motivo = false;
					bBajaTO = null;
					if (bAccesoTO != null)
						idOperacion = bAccesoTO.getIdOperacion();
					else
						bandera = false;

				} else {
					bBajaTO = fabrica.getBitacoraAccesoDAO()
							.findBitacoraAccesoByIdUsuarioMotivo(idOperacion,
									FechaHoraTO.getFecha(inicio),
									usuarioTO.getIdUsuario(),
									baja.getIdMotivo());
					motivo = true;
					if (bBajaTO != null)
						idOperacion = bBajaTO.getIdOperacion();
					else
						bandera = false;
				}

				if (bBajaTO != null && bAccesoTO != null) {
					for (int y = 0; y < listHorarioTO.size(); y++) {
						if (listHorarioTO.get(y).getFechaInicio().getTime() <= bAccesoTO
								.getFecha().getTime()
								&& listHorarioTO.get(y).getFechaTermino()
										.getTime() >= bAccesoTO.getFecha()
										.getTime()) {
							long tiempoInicio = bAccesoTO.getFecha().getTime()
									+ bAccesoTO.getHora().getTime();
							long tiempoFin = bBajaTO.getFecha().getTime()
									+ bBajaTO.getHora().getTime();

							long operacion = (tiempoFin - tiempoInicio + (long) 60000);

							BitacoraAsistenciaTO biAsisTO = fabrica
									.getBitacoraAsistenciaDAO()
									.findBitacoraAsistenciaByFechaEmpleadoConsiderada(
											FechaHoraTO.getFecha(bAccesoTO
													.getFecha()),
											arrDatosTO[x].getEmpleadoTO()
													.getIdEmpleado(), false);
							if (biAsisTO != null) {
								if (biAsisTO.getListMotivoTO()[0].getIdMotivo() == asistencia
										.getIdMotivo()) {

									arrDatosTO[x]
											.setHorasLaboradas(arrDatosTO[x]
													.getHorasLaboradas()
													+ (operacion / (long) 3600000));
								} else if (biAsisTO.getListMotivoTO()[0]
										.getIdMotivo() == festivo.getIdMotivo()) {

									arrDatosTO[x]
											.setHorasLaboradas(arrDatosTO[x]
													.getHorasLaboradas()
													+ ((operacion / (long) 3600000) * 2));
								}

							}
						}
					}
				}

			}
		}

		fabrica.getDatosNominaDAO().deleteDatosNomina();
		// calculo de las faltas, dias laborados
		for (int x = 0; x < arrDatosTO.length; x++) {
			BitacoraAsistenciaTO reciveTO = null;

			reciveTO = fabrica.getBitacoraAsistenciaDAO()
					.selectByRangoFechaEmpleadoMotivoConsiderada(
							FechaHoraTO.getFecha(inicio),
							FechaHoraTO.getFecha(fin),
							arrDatosTO[x].getEmpleadoTO().getIdEmpleado(),
							asistencia.getIdMotivo(), false);
			if (reciveTO != null)
				arrDatosTO[x]
						.setDiasLaborados(reciveTO.getListIdoperacion().length);

			reciveTO = fabrica.getBitacoraAsistenciaDAO()
					.selectByRangoFechaEmpleadoMotivoConsiderada(
							FechaHoraTO.getFecha(inicio),
							FechaHoraTO.getFecha(fin),
							arrDatosTO[x].getEmpleadoTO().getIdEmpleado(),
							falta.getIdMotivo(), false);
			if (reciveTO != null)
				arrDatosTO[x].setFaltas(reciveTO.getListIdoperacion().length);

			reciveTO = fabrica.getBitacoraAsistenciaDAO()
					.selectByRangoFechaEmpleadoMotivoConsiderada(
							FechaHoraTO.getFecha(inicio),
							FechaHoraTO.getFecha(fin),
							arrDatosTO[x].getEmpleadoTO().getIdEmpleado(),
							vacaciones.getIdMotivo(), false);
			if (reciveTO != null)
				arrDatosTO[x]
						.setDiasVacaciones(reciveTO.getListIdoperacion().length);

			reciveTO = fabrica.getBitacoraAsistenciaDAO()
					.selectByRangoFechaEmpleadoMotivoConsiderada(
							FechaHoraTO.getFecha(inicio),
							FechaHoraTO.getFecha(fin),
							arrDatosTO[x].getEmpleadoTO().getIdEmpleado(),
							festivo.getIdMotivo(), false);
			if (reciveTO != null)
				arrDatosTO[x].setDiasLaborados(arrDatosTO[x].getDiasLaborados()
						+ (reciveTO.getListIdoperacion().length) * 2);

			fabrica.getDatosNominaDAO().insertDatosNomina(arrDatosTO[x]);

		}
	}

	public void considerarRango(Date inicio, Date fin) {

		// proceso que coloca asistencias dependiendo de los accesos al sistema
		for (int x = 0; x < arrDatosTO.length; x++) {
			BitacoraAsistenciaTO biAsisTO = fabrica.getBitacoraAsistenciaDAO()
					.selectByRangoFechaEmpleadoConsiderada(
							FechaHoraTO.getFecha(inicio),
							FechaHoraTO.getFecha(fin),
							arrDatosTO[x].getEmpleadoTO().getIdEmpleado(),
							false);
			if (biAsisTO != null) {
				for (int y = 0; y < biAsisTO.getListIdoperacion().length; y++) {
					fabrica.getBitacoraAsistenciaDAO()
							.considerarBitacoraAsistencia(true,
									biAsisTO.getListIdoperacion()[y]);
				}
			}

		}

	}

	public static void main(String[] args) {
		ProcesoNomina n = new ProcesoNomina();

		n.horarioEnRango(FechaHoraTO.getFecha("2009/01/15"), FechaHoraTO
				.getFecha("2009/01/19"));

		n.listaMeses(FechaHoraTO.getFecha("2009/01/15"), FechaHoraTO
				.getFecha("2009/02/15"));

		/*n.considerarRango(FechaHoraTO.getFecha("2009/01/01"), FechaHoraTO
				.getFecha("2009/01/10"));*/
	}

}
